<?php
/*
From: http://www.phppan.com
*/

/*
[经典代码]
数字转字符串:
*/
char __b[32];
int __num = 28790;
char *__p;
__p = __b + sizeof(__b) - 1;
*__p= '\0';

do
{ 
    *--__p = (char) (__num % 10) + '0';
    __num /=10;
}
while (__num > 0);

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
/*
使用PHP的fsockopen函数实现获取大文件部分内容
*/
header("Content-type:text/html;charset=UTF-8");
 
$host = "downloads.php.net";
$port = 80;
$path = "/johannes/php-5.3.1RC1.tar.bz2";
$start = 0;
$length = 100;
 
$content = get_remote_content($host, $port, $path, $start, $length);
$content_length = strlen($content);
 
if (!empty($content)) {
    $file = array();
    if (preg_match("/Content-Length:.?(\d+)/", $content, $matches)) {
        $header_length = $matches[1];
        $content = substr($content, $content_length - $header_length);
 
        if (!empty($header_length)) {   //  更新start，可能需要记录当前位置
            $start = $start + $header_length;
        }
    }
}
echo $content;
 
//echo xdebug_time_index();
die();
 
/**
 * 获取远程文件内容
 * @param <type> $host 主机
 * @param <type> $port 端口
 * @param <type> $path 路径
 * @param <type> $start 开始位置
 * @return <type> 远程部分内容
 */
function get_remote_content($host, $port = 80, $path = "/", $start = 0, $length = -1) {
    $fp = fsockopen($host, $port, $errno, $errstr);
    if (!$fp) {
        return false;
    }
 
    $range = $start . "-";
    if ($length != -1) {
        $range .= $start + $length;
    }
 
    $out = "GET " . $path . " HTTP/1.1\r\n";
    $out .= "Host: " . $host . "\r\n";
    $out .= "Range:bytes=" .$range . "\r\n";  //  取start之后的内容
    $out .= "Connection: Close\r\n\r\n";
    fwrite($fp, $out);
    $buffer = '';
    while (!feof($fp)) {
        $buffer .= fgets($fp, 4096);
    }
    return $buffer;
}

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
/*
HashTable的数据结构
在Zend Engine中的HashTable的实现代码主要包括zend_hash.h, zend_hash.c这两个文件中。Zend HashTable包括两个主要的数据结构，其一是Bucket（桶）结构，另一个是HashTable结构。Bucket结构是用于保存数据的容器，而 HashTable结构则提供了对所有这些Bucket(或桶列)进行管理的机制。
*/
typedef struct bucket {
    ulong h;       /* Used for numeric indexing */
    uint nKeyLength;     /* key 长度 */
    void *pData;      /* 指向Bucket中保存的数据的指针 */
    void *pDataPtr;     /* 指针数据 */
    struct bucket *pListNext;   /* 指向HashTable桶列中下一个元素 */
    struct bucket *pListLast;    /* 指向HashTable桶列中前一个元素 */
    struct bucket *pNext;    /* 指向具有同一个hash值的桶列的后一个元素 */
    struct bucket *pLast;    /* 指向具有同一个hash值的桶列的前一个元素 */
    char arKey[1];      /* 必须是最后一个成员，key名称*/
} Bucket;
/*
Bucket 是一个可变长的结构体，由于 arKey 是 Bucket 的最后一个成员变量，通过 arKey 与 nKeyLength 结合可确定一个长度为 nKeyLength 的 key。这是C语言编程中的一个比较常用的技巧。
*/

typedef struct _hashtable {
    uint nTableSize;
    uint nTableMask;
    uint nNumOfElements;
    ulong nNextFreeElement;
    Bucket *pInternalPointer;
    Bucket *pListHead;
    Bucket *pListTail;
    Bucket **arBuckets;
    dtor_func_t pDestructor;
    zend_bool persistent;
    unsigned char nApplyCount;
    zend_bool bApplyProtection;
     
#if ZEND_DEBUG
    int inconsistent;
#endif
} HashTable;

/*
HashTable的状态，状态有四种：
状态值 含义
HT_IS_DESTROYING 正在删除所有的内容，包括arBuckets本身
HT_IS_DESTROYED 已删除，包括arBuckets本身
HT_CLEANING 正在清除所有的arBuckets指向的内容，但不包括arBuckets本身
HT_OK 正常状态，各种数据完全一致
*/
typedef struct _zend_hash_key {
    char *arKey;      /* hash元素key名称 */
    uint nKeyLength;     /* hash 元素key长度 */
    ulong h;       /* key计算出的hash值或直接指定的数值下标 */
} zend_hash_key;

/*
Zend HashTable的实现
*/
ZEND_API int _zend_hash_init(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC)
{
	uint i = 3;
	Bucket **tmp;

	SET_INCONSISTENT(HT_OK);

	if (nSize >= 0x80000000) {
		/* prevent overflow */
		ht->nTableSize = 0x80000000;
	} else {
		while ((1U << i) < nSize) {  /* 自动调整 nTableSize 至 2 的 n 次方 */
			i++;
		}
		ht->nTableSize = 1 << i;  /* i的最小值为3，因此HashTable大小最小为8 */
	}

	ht->nTableMask = ht->nTableSize - 1;
	ht->pDestructor = pDestructor;
	ht->arBuckets = NULL;
	ht->pListHead = NULL;
	ht->pListTail = NULL;
	ht->nNumOfElements = 0;
	ht->nNextFreeElement = 0;
	ht->pInternalPointer = NULL;
	ht->persistent = persistent;
	ht->nApplyCount = 0;
	ht->bApplyProtection = 1;
	
    /* 根据persistent使用不同方式分配arBuckets内存，并将其所有指针初始化为NULL*/
	/* Uses ecalloc() so that Bucket* == NULL */
	if (persistent) {
		tmp = (Bucket **) calloc(ht->nTableSize, sizeof(Bucket *));
		if (!tmp) {
			return FAILURE;
		}
		ht->arBuckets = tmp;
	} else {
		tmp = (Bucket **) ecalloc_rel(ht->nTableSize, sizeof(Bucket *));
		if (tmp) {
			ht->arBuckets = tmp;
		}
	}
	
	return SUCCESS;
}